import asyncio
import httpx
import smtplib
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from typing import Dict, List, Optional
from sqlalchemy.orm import Session
from app.models.database.models import NotificationConfig, ServiceConfig
from app.core.config.settings import settings
import logging
from datetime import datetime

logger = logging.getLogger(__name__)


class NotificationService:
    """通知服务"""

    def __init__(self):
        self.http_client = httpx.AsyncClient(timeout=30.0)

    async def send_switch_notification(
            self,
            service: ServiceConfig,
            from_status: str,
            to_status: str,
            reason: Optional[str] = None,
            operator: Optional[str] = None
    ):
        """发送切换通知"""

        # 获取激活的通知配置
        db = next(get_db())
        try:
            active_configs = db.query(NotificationConfig) \
                .filter(NotificationConfig.is_active == True) \
                .all()

            tasks = []
            for config in active_configs:
                task = self._send_notification_by_config(
                    config=config,
                    service=service,
                    from_status=from_status,
                    to_status=to_status,
                    reason=reason,
                    operator=operator
                )
                tasks.append(task)

            await asyncio.gather(*tasks, return_exceptions=True)

        finally:
            db.close()

    async def _send_notification_by_config(
            self,
            config: NotificationConfig,
            service: ServiceConfig,
            from_status: str,
            to_status: str,
            reason: Optional[str],
            operator: Optional[str]
    ):
        """根据配置发送通知"""

        try:
            if config.type == "email":
                await self._send_email_notification(
                    config=config.config,
                    service=service,
                    from_status=from_status,
                    to_status=to_status,
                    reason=reason,
                    operator=operator
                )
            elif config.type == "webhook":
                await self._send_webhook_notification(
                    config=config.config,
                    service=service,
                    from_status=from_status,
                    to_status=to_status,
                    reason=reason,
                    operator=operator
                )
            elif config.type == "sms":
                await self._send_sms_notification(
                    config=config.config,
                    service=service,
                    from_status=from_status,
                    to_status=to_status,
                    reason=reason,
                    operator=operator
                )

        except Exception as e:
            logger.error(f"Failed to send {config.type} notification: {e}")

    async def _send_email_notification(
            self,
            config: Dict,
            service: ServiceConfig,
            from_status: str,
            to_status: str,
            reason: Optional[str],
            operator: Optional[str]
    ):
        """发送邮件通知"""

        if not settings.smtp_server:
            logger.warning("SMTP server not configured")
            return

        try:
            # 构建邮件内容
            subject = f"灾备切换通知 - {service.name}"
            body = self._build_email_content(
                service=service,
                from_status=from_status,
                to_status=to_status,
                reason=reason,
                operator=operator
            )

            # 创建邮件
            msg = MIMEMultipart()
            msg['From'] = settings.from_email
            msg['To'] = ', '.join(config.get('recipients', []))
            msg['Subject'] = subject

            msg.attach(MIMEText(body, 'html'))

            # 发送邮件
            server = smtplib.SMTP(settings.smtp_server, settings.smtp_port)
            if settings.smtp_use_tls:
                server.starttls()

            if settings.smtp_username and settings.smtp_password:
                server.login(settings.smtp_username, settings.smtp_password)

            server.send_message(msg)
            server.quit()

            logger.info(f"Email notification sent for service {service.name}")

        except Exception as e:
            logger.error(f"Failed to send email notification: {e}")
            raise

    async def _send_webhook_notification(
            self,
            config: Dict,
            service: ServiceConfig,
            from_status: str,
            to_status: str,
            reason: Optional[str],
            operator: Optional[str]
    ):
        """发送Webhook通知"""

        webhook_urls = config.get('urls', [])

        payload = {
            "service": {
                "id": service.id,
                "name": service.name,
                "primary_url": service.primary_url,
                "backup_url": service.backup_url
            },
            "switch": {
                "from_status": from_status,
                "to_status": to_status,
                "reason": reason,
                "operator": operator,
                "timestamp": datetime.utcnow().isoformat()
            },
            "type": "disaster_recovery_switch"
        }

        tasks = []
        for url in webhook_urls:
            task = self._send_single_webhook(url, payload)
            tasks.append(task)

        await asyncio.gather(*tasks, return_exceptions=True)

    async def _send_single_webhook(self, url: str, payload: Dict):
        """发送单个Webhook"""
        try:
            response = await self.http_client.post(
                url,
                json=payload,
                headers={"Content-Type": "application/json"}
            )
            response.raise_for_status()
            logger.info(f"Webhook notification sent to {url}")
        except Exception as e:
            logger.error(f"Failed to send webhook to {url}: {e}")

    async def _send_sms_notification(
            self,
            config: Dict,
            service: ServiceConfig,
            from_status: str,
            to_status: str,
            reason: Optional[str],
            operator: Optional[str]
    ):
        """发送短信通知（需要集成具体的短信服务商）"""

        # 这里可以集成阿里云短信、腾讯云短信等服务
        logger.info("SMS notification requested (implementation needed)")

    def _build_email_content(
            self,
            service: ServiceConfig,
            from_status: str,
            to_status: str,
            reason: Optional[str],
            operator: Optional[str]
    ) -> str:
        """构建邮件内容"""

        return f"""
        <html>
        <body>
            <h2>灾备切换通知</h2>
            <p><strong>服务名称:</strong> {service.name}</p>
            <p><strong>切换时间:</strong> {datetime.utcnow().strftime('%Y-%m-%d %H:%M:%S')} UTC</p>
            <p><strong>切换类型:</strong> {from_status} → {to_status}</p>
            <p><strong>操作人:</strong> {operator or '系统'}</p>
            <p><strong>切换原因:</strong> {reason or '未指定'}</p>

            <h3>服务信息</h3>
            <ul>
                <li>主服务: {service.primary_url}</li>
                <li>备份服务: {service.backup_url}</li>
                <li>健康检查端点: {service.health_check_endpoint}</li>
            </ul>

            <p>请及时检查服务状态，确保切换成功。</p>

            <p>此邮件由灾备控制系统自动发送。</p>
        </body>
        </html>
        """

    async def send_health_alert(
            self,
            service: ServiceConfig,
            alert_type: str,
            details: Dict
    ):
        """发送健康告警"""

        # 构建告警内容
        alert_content = {
            "service": {
                "id": service.id,
                "name": service.name,
                "url": service.primary_url if service.is_active else service.backup_url
            },
            "alert": {
                "type": alert_type,
                "details": details,
                "timestamp": datetime.utcnow().isoformat()
            }
        }

        # 发送告警通知
        db = next(get_db())
        try:
            active_configs = db.query(NotificationConfig) \
                .filter(NotificationConfig.is_active == True) \
                .all()

            tasks = []
            for config in active_configs:
                task = self._send_alert_notification(config, alert_content)
                tasks.append(task)

            await asyncio.gather(*tasks, return_exceptions=True)

        finally:
            db.close()

    async def _send_alert_notification(
            self,
            config: NotificationConfig,
            alert_content: Dict
    ):
        """发送告警通知"""

        try:
            if config.type == "email":
                await self._send_email_alert(config.config, alert_content)
            elif config.type == "webhook":
                await self._send_webhook_alert(config.config, alert_content)

        except Exception as e:
            logger.error(f"Failed to send alert notification: {e}")

    async def _send_email_alert(self, config: Dict, alert_content: Dict):
        """发送邮件告警"""

        try:
            subject = f"健康告警 - {alert_content['service']['name']}"
            body = f"""
            <html>
            <body>
                <h2>健康告警</h2>
                <p><strong>服务:</strong> {alert_content['service']['name']}</p>
                <p><strong>告警类型:</strong> {alert_content['alert']['type']}</p>
                <p><strong>时间:</strong> {alert_content['alert']['timestamp']}</p>
                <p><strong>详情:</strong></p>
                <pre>{alert_content['alert']['details']}</pre>
            </body>
            </html>
            """

            # 使用相同的邮件发送逻辑
            # ... (省略重复代码)

        except Exception as e:
            logger.error(f"Failed to send email alert: {e}")

    async def close(self):
        """关闭HTTP客户端"""
        await self.http_client.aclose()


# 全局通知服务实例
notification_service = NotificationService()

# 导入get_db函数
from app.core.config.database import get_db